import calendar
from datetime import datetime, timedelta
from os import path

from django.db import transaction
from django.db.models import Count, Sum, F, FloatField, DateField
from django.db.models.functions import ExtractDay, ExtractWeek, Trunc, TruncDay, TruncMonth
from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.base import View

from pyecharts import options as opts
from pyecharts.charts import Bar, Page as EPage, Pie, Calendar, Line
from store.models import Goods, StorageRecord, StorageRecordOfGoods, TicketSetting, Customer



def index(request):
    goods = Goods.objects.filter(quantity_in_store__gt=0).select_related("category")
    is_danger = TicketSetting.objects.all()[0].is_danger
    danger_goods = Goods.objects.filter(quantity_in_store__lt=is_danger).count()
    return render(request, 'index.html', {"goods": goods, "goods_len": len(goods), "is_danger": is_danger, "danger_goods": danger_goods})


def ticket(request, id):
    # max_line = 10
    this_ticket = StorageRecord.objects.get(id=id)
    goods = StorageRecordOfGoods.objects.filter(storage_record=this_ticket).select_related("goods")
    sum_goods = StorageRecordOfGoods.objects.filter(storage_record=this_ticket).aggregate(sum=Sum("amount"))
    ticket_title = TicketSetting.objects.all()[0]
    return render(request, "ticket.html", {"goods": goods, "ticket": this_ticket, "sum_goods": sum_goods["sum"], "title":ticket_title})


class ChartsView(LoginRequiredMixin, View):
    def get(self, request):
        today_record = StorageRecord.objects.filter(create_time__gt=(datetime.today()-timedelta(days=1)))
        last_week_record = StorageRecord.objects.filter(create_time__gt=(datetime.today()-timedelta(weeks=1)))
        last_month_record = StorageRecord.objects.filter(create_time__gt=(datetime.today()-timedelta(days=30)))

        today_income = StorageRecordOfGoods.objects.filter(storage_record__in=today_record).\
            extra(select={"income": "SUM((pries-cost)*amount)"}).values("income")
        last_week_income = StorageRecordOfGoods.objects.filter(storage_record__in=last_week_record).\
                extra(select={"income": "SUM((pries-cost)*amount)"}).values("income")
        last_month_income = StorageRecordOfGoods.objects.filter(storage_record__in=last_month_record).\
                extra(select={"income": "SUM((pries-cost)*amount)"}).values("income")

        page = EPage(page_title="报表", layout=EPage.SimplePageLayout)
        three_income = Pie()
        three_income.__dict__.update({"width":"1094px","height":"417px","top":"33px","left":"7px"})
        page.add(three_income.add(
            series_name="收入",
            data_pair=[list(z) for z in zip(["今日收入", "七天内收入", "三十天内收入"],
                                            [today_income[0]["income"], last_week_income[0]["income"], last_month_income[0]["income"]])],
            center=["50%", "50%"],
        ).set_global_opts(
            title_opts=opts.TitleOpts(
                title="收入统计图",
                pos_left="center",
                pos_top="20",
                # title_textstyle_opts=opts.TextStyleOpts(color="#fff"),
            ),
            legend_opts=opts.LegendOpts(is_show=True),
        ).set_series_opts(
            tooltip_opts=opts.TooltipOpts(
                trigger="item", formatter="{b}: ￥{c} "
            ),
            label_opts=opts.LabelOpts(formatter="￥{c}")
            # label_opts=opts.LabelOpts(color="rgba(255, 255, 255, 0.3)"),
        )
        )

        this_year = datetime(int(datetime.now().strftime("%Y")), 1, 1).year
        # 每个月的收入
        this_year_income = StorageRecordOfGoods.objects.filter(storage_record__create_time__year=this_year).aggregate(sum=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField()))
        this_year_every_month_income = StorageRecordOfGoods.objects.filter(storage_record__create_time__year=this_year).annotate(
            month=TruncMonth("storage_record__create_time", output_field=DateField())).values("month").annotate(
            sum=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())).values("month", "sum")
        this_year_every_month_bar = Bar()
        this_year_every_month_bar.__dict__.update(
            {"width":"1098px","height":"400px","top":"471.66668701171875px","left":"6px"})
        page.add(
            this_year_every_month_bar.add_xaxis([i["month"].month for i in this_year_every_month_income])
                .add_yaxis("收入", [i["sum"] for i in this_year_every_month_income])
                .set_global_opts(
                # xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
                title_opts=opts.TitleOpts(title="每个月收入", subtitle="共计："+str(this_year_income["sum"])),
            )
        )

        # 今年日历图
        this_year_everyday_income = StorageRecordOfGoods.objects.filter(storage_record__create_time__year=this_year).annotate(
            date=Trunc("storage_record__create_time", "day", output_field=DateField())).values("date").annotate(
            sum=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())).values("date", "sum")
        rili_data = [[str(i["date"]), i["sum"]] for i in this_year_everyday_income]
        this_year_calendar = Calendar()
        this_year_calendar.__dict__.update({"width":"1098px","height":"268px","top":"471.66668701171875px","left":"6px"})
        page.add(
            this_year_calendar.add(
                "",
                rili_data,
                calendar_opts=opts.CalendarOpts(
                    range_=datetime.now().strftime("%Y"),
                    daylabel_opts=opts.CalendarDayLabelOpts(name_map="cn"),
                    monthlabel_opts=opts.CalendarMonthLabelOpts(name_map="cn"),
                ),
            )
            .set_global_opts(
                title_opts=opts.TitleOpts(title="今年收入情况"),
                visualmap_opts=opts.VisualMapOpts(
                    max_=max(rili_data, key=lambda x: x[1])[1],
                    min_=0,
                    orient="horizontal",
                    is_piecewise=True,
                    pos_top="230px",
                    pos_left="100px",
                ),
            )
        )

        # 销量排行
        last_week_goods_topic = StorageRecordOfGoods.objects.filter(storage_record__in=last_week_record).\
            values("goods").\
            annotate(income=Sum((F("pries")-F("cost"))*F("amount"), output_field=FloatField())).\
            order_by("-income")[:7].values("goods__name", "income")
        last_month_goods_topic = StorageRecordOfGoods.objects.filter(storage_record__in=last_month_record). \
                                    values("goods"). \
                                    annotate(
            income=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())). \
                                    order_by("-income")[:7].values("goods__name", "income")
        last_week_goods_topic_bar = Bar()
        last_week_goods_topic_bar.__dict__.update({"width":"592px","height":"500px","top":"761.3333740234375px","left":"8px"})
        page.add(
            last_week_goods_topic_bar.add_xaxis([i["goods__name"] for i in last_week_goods_topic])
                .add_yaxis("商品", [i["income"] for i in last_week_goods_topic])
                .set_global_opts(
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
                title_opts=opts.TitleOpts(title="周销量排行", subtitle="商品"),
            )
        )
        last_month_goods_topic_bar = Bar()
        last_month_goods_topic_bar.__dict__.update({"width":"527px","height":"500px","top":"761px","left":"612px"})
        page.add(
            last_month_goods_topic_bar.add_xaxis([i["goods__name"] for i in last_month_goods_topic])
                .add_yaxis("商品", [i["income"] for i in last_month_goods_topic])
                .set_global_opts(
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
                title_opts=opts.TitleOpts(title="月销量排行", subtitle="商品"),
            )
        )

        last_week_organization_topic = StorageRecordOfGoods.objects.filter(storage_record__in=last_week_record).\
        values("storage_record__organization").annotate(
            income=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())).order_by(
            "-income")[:7].values("storage_record__organization__organization", "income")
        last_month_organization_topic = StorageRecordOfGoods.objects.filter(storage_record__in=last_month_record).\
        values("storage_record__organization").annotate(
            income=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())).order_by(
            "-income")[:7].values("storage_record__organization__organization", "income")
        last_week_organization_topic_bar = Bar()
        last_week_organization_topic_bar.__dict__.update({"width":"593px","height":"500px","top":"1272.666748046875px","left":"8px"})
        page.add(
            last_week_organization_topic_bar.add_xaxis([i["storage_record__organization__organization"] for i in last_week_organization_topic])
                .add_yaxis("商家", [i["income"] for i in last_week_organization_topic])
                .set_global_opts(
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
                title_opts=opts.TitleOpts(title="周销量排行", subtitle="商家"),
            )
        )
        last_month_organization_topic_bar = Bar()
        last_month_organization_topic_bar.__dict__.update({"width":"527px","height":"500px","top":"1272.3333740234375px","left":"613px"})
        page.add(
            last_month_organization_topic_bar.add_xaxis([i["storage_record__organization__organization"] for i in last_month_organization_topic])
                .add_yaxis("商家", [i["income"] for i in last_month_organization_topic])
                .set_global_opts(
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
                title_opts=opts.TitleOpts(title="月销量排行", subtitle="商家"),
            )
        )

        # 按天分组
        # StorageRecordOfGoods.obje cts.annotate(day=ExtractDay("storage_record__create_time")).values("day").annotate(
            # income=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())).values("income")

        # StorageRecordOfGoods.objects.annotate(
        #     date=Trunc("storage_record__create_time", "day", output_field=DateField())).values("date").annotate(
        #     sum=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())).values("date", "sum")
        #
        return HttpResponse(page.render_embed())


def search(request):
    if request.method == "POST":
        goods = Goods.objects.filter(name__contains=request.POST.get("good_name"), quantity_in_store__gt=0)
        is_danger = TicketSetting.objects.all()[0].is_danger
        return render(request, 'index.html', {"goods": goods, "goods_len": len(goods), "is_search": True, "is_danger": is_danger})


def buhuo(request):
    goods = Goods.objects.all().order_by('quantity_in_store')
    is_danger = TicketSetting.objects.all()[0].is_danger
    return render(request, "buhuo.html", {"goods": goods, "is_danger": is_danger})


def add_to_store(request):
    # 从仓库中拿出来放到购物车中，如果失败则回滚
    id = int(request.POST.get("id", ""))
    amount = int(request.POST.get("amount", ""))
    if not amount:
        HttpResponse("0")
    if request.method == "POST":
        with transaction.atomic():
            Goods.objects.filter(id=id).update(quantity_in_store=F('quantity_in_store')+amount)
    return HttpResponse("1")


def ticket_list(request):
    all_ticket = StorageRecord.objects.all().order_by("-create_time")
    return render(request, "ticket_list.html", {"all_ticket": all_ticket})


class MonthAmount(View):
    def get(self, request):
        orgs = Customer.objects.all()
        return render(request, "month_amount.html", {"orgs": orgs})

    def post(self, request):
        org_id = int(request.POST.get("org"))
        orgs = Customer.objects.all()
        # date_month = request.POST.get("date")
        # year, month = date_month.split('-')
        # _, month_range = calendar.monthrange(int(year), int(month))
        # first_day = datetime(year=int(year), month=int(month), day=1)
        # last_day = datetime(year=int(year), month=int(month), day=month_range)
        try:
            first_day = datetime.strptime(request.POST.get("startTime", ''), '%Y-%m-%d')
            last_day = datetime.strptime(request.POST.get("endTime", ''), '%Y-%m-%d')
        except:
            return render(request, "month_amount.html", {"orgs": orgs})
        this_month = StorageRecord.objects.filter(organization=Customer.objects.get(id=org_id), create_time__range=(first_day, last_day))
        if len(this_month) == 0:
            return render(request, "month_amount.html", {"noresult": True, "orgs": orgs})
        amount = this_month.aggregate(sum=Sum('total_pries'))['sum']
        return render(request, 'month_amount.html', {"orgs": orgs, "this_month": this_month, "amount": amount})


def choice_date_range_of_income(request):
    if request.method == "GET":
        return render(request, 'choice_date.html')
    else:
        try:
            start_date = datetime.strptime(request.POST.get("startTime", ''), '%Y-%m-%d')
            end_date = datetime.strptime(request.POST.get("endTime", ''), '%Y-%m-%d')
        except:
            return render(request, 'choice_date.html')

        result = StorageRecordOfGoods.objects.filter(storage_record__create_time__range=(start_date, end_date))\
            .annotate(every_daty=TruncDay("storage_record__create_time", output_field=DateField())).values("every_daty").annotate(
            sum=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField())).values_list("every_daty", "sum")
        if len(result) == 0:
            return render(request, 'choice_date.html', {"line": "没有找到收入。"})
        sum_income = StorageRecordOfGoods.objects.filter(storage_record__create_time__range=(start_date, end_date)).aggregate(sum=Sum((F("pries") - F("cost")) * F("amount"), output_field=FloatField()))
        result = list(zip(*result))
        line = Line().set_global_opts(
            tooltip_opts=opts.TooltipOpts(is_show=False),
            xaxis_opts=opts.AxisOpts(type_="category", axislabel_opts=opts.LabelOpts(rotate=-35)),
            yaxis_opts=opts.AxisOpts(
                type_="value",
                axistick_opts=opts.AxisTickOpts(is_show=True),
                splitline_opts=opts.SplitLineOpts(is_show=True),
            ),
            title_opts=opts.TitleOpts(title=sum_income['sum'], pos_left="center", subtitle="共计收入"),
        ).add_xaxis(xaxis_data=result[0])\
        .add_yaxis(
            series_name="",
            y_axis=result[1],
            symbol="emptyCircle",
            is_symbol_show=True,
            label_opts=opts.LabelOpts(is_show=False),
        )
        return render(request, 'choice_date.html', {"line": line.render_embed()})
